home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / LZ.ZIP / LZDCMP.ASM < prev    next >
Assembly Source File  |  1986-07-01  |  6KB  |  259 lines

  1.     title    lzdcmp - file decompressor using limpel-ziev algorithm
  2.  
  3. ;Tom Pfau
  4. ;Digital Equipment Corporation
  5. ;Parsippany, NJ
  6.  
  7. ;Constants
  8. clear        equ    256
  9. eof        equ    257
  10. first_free    equ    258
  11. maxmax        equ    4096
  12.  
  13.     include    macros.mlb
  14.  
  15. ;Hash table entry
  16. hash_rec    struc
  17. next    dw    ?            ; prefix code
  18. char    db    ?            ; suffix char
  19. hash_rec    ends
  20.  
  21. ;Declare segments
  22. code    segment byte public 'code'
  23. code    ends
  24. stack    segment word stack 'data'
  25.     dw    128 dup (?)
  26. stack    ends
  27. data    segment word public 'data'
  28. data    ends
  29. memory    segment para public 'memory'
  30. hash    label    hash_rec
  31. memory    ends
  32.  
  33. ;Start coding
  34. code    segment
  35.     assume    cs:code,ds:data,ss:stack,es:data
  36.  
  37. start    proc    far
  38.     mov    bx,seg hash        ;End of program
  39.     mov    ax,ds            ;Beginning of program
  40.     sub    bx,ax            ;Size of program
  41.     inc    bx            ;Make sure
  42.     setmem    bx            ;Set program size
  43.     mov    bx,data            ;Address data segment
  44.     mov    es,bx
  45.     mov    ds,bx
  46.     print    input_prompt        ;Get file names
  47.     input    input_file
  48.     print    crlf
  49.     print    output_prompt
  50.     input    output_file
  51.     print    crlf
  52.     mov    al,input_file+1        ;Terminate with nulls
  53.     xor    ah,ah
  54.     mov    si,ax
  55.     mov    input_file+2[si],0
  56.     mov    al,output_file+1
  57.     mov    si,ax
  58.     mov    output_file+2[si],0
  59.     hopen    input_file+2,0        ;Open input and output
  60.     mov    input_handle,ax
  61.     hcreat    output_file+2,0
  62.     mov    output_handle,ax
  63.     call    decompress        ;Decompress files
  64.     hclose    input_handle
  65.     hclose    output_handle
  66.     exit                ;Done
  67. start    endp
  68.  
  69. data    segment
  70. input_prompt    db    'Input file: $'
  71. output_prompt    db    'Output file: $'
  72. input_file    db    80,0,80 dup (?)
  73. output_file    db    80,0,80 dup (?)
  74. crlf        db    13,10,'$'
  75. input_handle    dw    ?
  76. output_handle    dw    ?
  77. data    ends
  78.  
  79. decompress    proc    near
  80.     malloc    768            ;Allocate space for hash table
  81.     mov    hash_seg,ax        ;Save segment address
  82.     hread    input_handle,input_buffer,1024    ;Read from input
  83. l1:    call    read_code        ;Get a code
  84.     cmp    ax,eof            ;End of file?
  85.     jne    l2            ;no
  86.     cmp    output_offset,0        ;Data in output buffer?
  87.     je    l1a            ;no
  88.     hwrite    output_handle,output_buffer,output_offset    ;Flush buffer
  89. l1a:    ret                ;done
  90. l2:    cmp    ax,clear        ;Clear code?
  91.     jne    l7            ;no
  92.     call    init_tab        ;Initialize table
  93.     call    read_code        ;Read next code
  94.     mov    cur_code,ax        ;Initialize variables
  95.     mov    old_code,ax
  96.     mov    k,al
  97.     mov    fin_char,al
  98.     mov    al,k
  99.     call    write_char        ;Write character
  100.     jmp    l1            ;Get next code
  101. l7:    mov    cur_code,ax        ;Save new code
  102.     mov    in_code,ax
  103.     mov    es,hash_seg        ;Point to hash table
  104.     cmp    ax,free_code        ;Code in table? (k<w>k<w>k)
  105.     jl    l11            ;yes
  106.     mov    ax,old_code        ;get previous code
  107.     mov    cur_code,ax        ;make current
  108.     mov    al,fin_char        ;get old last char
  109.     push    ax            ;push it
  110.     inc    stack_count
  111. l11:    cmp    cur_code,255        ;Code or character?
  112.     jle    l15            ;Char
  113.     mov    bx,cur_code        ;Convert code to address
  114.     call    index
  115.     mov    al,es:2[bx]        ;Get suffix char
  116.     push    ax            ;push it
  117.     inc    stack_count
  118.     mov    ax,es:[bx]        ;Get prefix code
  119.     mov    cur_code,ax        ;Save it
  120.     jmp    l11            ;Translate again
  121. l15:    push    ds            ;Restore seg reg
  122.     pop    es
  123.     mov    ax,cur_code        ;Get code
  124.     mov    fin_char,al        ;Save as final, k
  125.     mov    k,al
  126.     push    ax            ;Push it
  127.     inc    stack_count
  128.     mov    cx,stack_count        ;Pop stack
  129.     jcxz    l18            ;If anything there
  130. l17:    pop    ax
  131.     call    write_char
  132.     loop    l17
  133. l18:    mov    stack_count,cx        ;Clear count on stack
  134.     call    add_code        ;Add new code to table
  135.     mov    ax,in_code        ;Save input code
  136.     mov    old_code,ax
  137.     mov    bx,free_code        ;Hit table limit?
  138.     cmp    bx,max_code
  139.     jl    l23            ;Less means no
  140.     cmp    nbits,12        ;Still within twelve bits?
  141.     je    l23            ;no (next code should be clear)
  142.     inc    nbits            ;Increase code size
  143.     shl    max_code,1        ;Double max code
  144. l23:    jmp    l1            ;Get next code
  145. decompress    endp    
  146.  
  147. data    segment
  148. hash_seg    dw    ?
  149. cur_code    dw    ?
  150. old_code    dw    ?
  151. in_code        dw    ?
  152. free_code    dw    first_free
  153. stack_count    dw    0
  154. nbits        dw    9
  155. max_code    dw    512
  156. fin_char    db    ?
  157. k        db    ?
  158. data    ends
  159.  
  160. read_code    proc    near
  161.     mov    ax,bit_offset        ;Get bit offset
  162.     add    ax,nbits        ;Adjust by code size
  163.     xchg    bit_offset,ax        ;Swap
  164.     mov    cx,8            ;Calculate byte offset
  165.     xor    dx,dx
  166.     div    cx
  167.     cmp    ax,1021            ;Approaching end of buffer?
  168.     jl    rd0            ;no
  169.     push    dx            ;Save offset in byte
  170.     add    dx,nbits        ;Calculate new bit offset
  171.     mov    bit_offset,dx
  172.     mov    cx,1024            ;1k buffer
  173.     mov    bp,ax            ;save byte offset
  174.     sub    cx,ax            ;Calculate bytes left
  175.     add    ax,offset input_buffer    ;Point to char
  176.     mov    si,ax
  177.     lea    di,input_buffer        ;Point to beginning of buffer
  178. rep    movsb                ;Move last chars down
  179.     hread    input_handle,[di],bp    ;Fill rest of buffer
  180.     xor    ax,ax            ;Clear ax
  181.     pop    dx            ;Restore offset in byte
  182. rd0:    add    ax,offset input_buffer    ;Point to char
  183.     mov    si,ax
  184.     lodsw                ;Get word
  185.     mov    bx,ax            ;Save in AX
  186.     lodsb                ;Next byte
  187.     mov    cx,dx            ;Offset in byte
  188.     jcxz    rd2            ;If zero, skip shifts
  189. rd1:    shr    al,1            ;Put code in low (code size) bits of BX
  190.     rcr    bx,1
  191.     loop    rd1
  192. rd2:    mov    ax,bx            ;put code in ax
  193.     mov    bx,nbits        ;mask off unwanted bits
  194.     sub    bx,9
  195.     shl    bx,1
  196.     and    ax,masks[bx]
  197.     ret
  198. read_code    endp
  199.  
  200. data    segment
  201. masks        dw    1ffh,3ffh,7ffh,0fffh
  202. input_buffer    db    1024 dup (?)
  203. bit_offset    dw    0
  204. data    ends
  205.  
  206. init_tab    proc    near
  207.     mov    nbits,9            ;Initialize variables
  208.     mov    max_code,512
  209.     mov    free_code,first_free
  210.     ret
  211. init_tab    endp
  212.  
  213. write_char    proc    near
  214.     mov    di,output_offset    ;Get offset in buffer
  215.     cmp    di,1024            ;Full?
  216.     jl    wc1            ;no
  217.     push    ax            ;Save registers
  218.     push    cx
  219.     hwrite    output_handle,output_buffer,di    ;Write buffer to file
  220.     pop    cx
  221.     pop    ax
  222.     mov    di,0            ;Point to beginning of buffer
  223.     mov    output_offset,di
  224. wc1:    lea    di,output_buffer[di]    ;Point into buffer
  225.     stosb                ;Store char
  226.     inc    output_offset        ;Increment number of chars in buffer
  227.     ret
  228. write_char    endp
  229.  
  230. data    segment
  231. output_offset    dw    0
  232. output_buffer    db    1024 dup (?)
  233. data    ends
  234.  
  235. index        proc    near
  236.     mov    bp,bx            ;bx = bx * 3 (3 byte entries)
  237.     shl    bx,1            ;bp = bx
  238.     add    bx,bp            ;bx = bx * 2 + bp
  239.     ret
  240. index        endp
  241.  
  242. add_code    proc    near
  243.     mov    bx,free_code        ;Get new code
  244.     call    index            ;convert to address
  245.     push    es            ;point to hash table
  246.     mov    es,hash_seg
  247.     mov    al,k            ;get suffix char
  248.     mov    es:[bx].char,al        ;save it
  249.     mov    ax,old_code        ;get prefix code
  250.     mov    es:[bx].next,ax        ;save it
  251.     pop    es
  252.     inc    free_code        ;set next code
  253.     ret
  254. add_code    endp
  255.  
  256. code    ends
  257.  
  258.     end    start
  259.